home *** CD-ROM | disk | FTP | other *** search
- /*
-
- © 1990 by Apple Computer, Inc.
- Ken Doyle - C Translation of ProgressWindoid.p (written by Chris Thorman)
- All Rights Reserved
-
- Permission granted for any kind of use as long as this notice is retained.
-
- Apple makes no claims as to the correctness or value of this software for
- any purpose. In fact, this software may well have bugs which will crash
- your machine at crucial moments.
- */
-
- /*
- ProgressWindoid (WindowName, Loc, [Width, Text, Fraction, TextFont, TextSize])
-
- This HyperCard external window command creates a windoid that can be used
- to show progress of a lengthy operation.
-
- The XFCN is called once and if successful, leaves an XWindoid which
- HyperCard will subsequently manage. A successful call is indicated
- by an empty return value from the XFCN. If the return value is not
- empty, then it should be interpreted as an error message.
-
- All interaction with the window takes place by getting and setting
- its properties (see below), and through HyperCard’s open, close, show,
- and hide commands.
-
- The WindowName argument is the name that the window will be given. It
- is required. After creating the window, this name will be used from
- HyperTalk to refer to it.
-
- The Loc argument is the point that will become the upper-left corner
- of the windoid. It is a two-item string in the form “20,50”. It is
- a card-relative number, not screen relative. It is required.
-
- The optional Width argument is total width of the windoid in pixels. The
- minimum width is 140 pixels. The maximum is 1200 pixels. The default
- is 250 pixels.
-
- The optional Text argument is the text that appears above the
- progress bar in the windoid. It may be empty. It defaults to “Progress:”.
-
- The optional Fraction argument is the Fraction that the XWindoid
- starts with when it is created. It is a floating point number between
- 0.0 and 1.0. It defaults to 0.0.
-
- The optional TextFont argument is the font that will be used for the text
- in the windoid. The name of the font (e.g. “Helvetica”) is used to specify
- the font. The default font is whatever font corresponds to 0 on the current
- system (usually Geneva).
-
- The optional TextSize argument is the size of the text in the window. It
- is 12 by default. The minimum size is 1 point and the maximum size is 127
- points.
-
- All of the optional arguments correspond to HyperCard properties of the
- windoid. These are: the width, the text, the fraction, the textFont, and
- the textSize.
-
- In addition to these special properties, the windoid also supports
- HyperCard’s standard window properties: the loc, the visible, and the
- properties (which returns a list of the special properties of the windoid).
-
- */
-
- #include <Memory.h>
- #include <Fonts.h>
- #include <FixMath.h>
-
- #include <HyperXCmd.h>
-
- #define kMinParams 2
- #define kMaxParams 7
-
- #define kTextTopSpace 5
- #define kTextBottomSpace 5
- #define kTextLeftSideSpace 20
-
- #define kProgBarSideSpace 20
-
- #define kProgBarHeight 20
- #define kProgBarBottomSpace 20
-
- #define kFract0 0
- #define kFract1 0x40000000
-
- /* Since the extended type doesn't work well in Think C, the windowFraction field is a Fract
- rather than an extended (as in the Pascal example). Places in the code where the parameter
- is used are changed accordingly. In particular, FracMul is used to multiply windowFraction
- by the progress bar width and the Frac2X and X2Frac conversion routines are used when calling
- the HyperCard ExtToStr and StrToExt routines.
- */
-
- struct ProgressWindoidInfoRecord {
- Str255 windowText;
- Fract windowFraction;
- short progBarTop; /* Cached here, but could be determined from txSize */
- short progBarWidth; /* Cached here, but could be determined from portRect */
- };
-
- typedef struct ProgressWindoidInfoRecord ProgressWindoidInfoRecord;
- typedef ProgressWindoidInfoRecord *ProgressWindoidInfoPtr, **ProgressWindoidInfoHandle;
-
-
- #define ExitWithError(errorMsg) \
- { \
- SetErrorResult(paramPtr, (StringPtr) errorMsg); \
- return; \
- }
-
- /* Prototypes */
- void SetErrorResult(XCmdPtr paramPtr, StringPtr errMsg);
- void LimitFractionValue(Fract *fraction);
- void LimitWidthValue(short *windWidth);
- void LimitTextSizeValue(short *textSize);
- void LimitTextSizeValue(short *textSize);
- void DoSetup(XCmdPtr paramPtr);
- void KillXWindow(XCmdPtr paramPtr, ProgressWindoidInfoHandle progWindInfo, WindowPtr theWindow);
- void DrawProgText(XCmdPtr paramPtr, ProgressWindoidInfoHandle progWindInfo, WindowPtr theWindow);
- void DrawProgBar(XCmdPtr paramPtr, ProgressWindoidInfoHandle progWindInfo, WindowPtr theWindow);
- void DoUpdate(XCmdPtr paramPtr, ProgressWindoidInfoHandle progWindInfo, WindowPtr theWindow);
- void DoMouseDown(XCmdPtr paramPtr, ProgressWindoidInfoHandle progWindInfo,
- WindowPtr theWindow, EventRecord *theEvent);
- Handle GetProperty(XCmdPtr paramPtr, ProgressWindoidInfoHandle progWindInfo,
- WindowPtr theWindow, StringPtr propName);
- void SetProperty(XCmdPtr paramPtr, ProgressWindoidInfoHandle progWindInfo,
- WindowPtr theWindow, StringPtr propName, Handle propVal);
- void ProcessEvent(XCmdPtr paramPtr, XWEventInfoPtr myXWEventInfoPtr,
- WindowPtr myWindow, EventRecord *myEvent);
- void DoEvent(XCmdPtr paramPtr);
-
-
- /* Main Entry Point */
- pascal void main(XCmdPtr paramPtr)
- {
- if (paramPtr->paramCount == -1)
- DoEvent(paramPtr);
- else
- DoSetup(paramPtr);
- }
-
- void SetErrorResult(XCmdPtr paramPtr, StringPtr errMsg)
- {
- Str255 tempStr = "\p•••••••• Error: ";
- short len;
-
- len = tempStr[0];
- BlockMove(&errMsg[1], &tempStr[len+1], errMsg[0]);
- len += errMsg[0];
- tempStr[0] = len;
- paramPtr->returnValue = PasToZero(paramPtr, tempStr);
- }
-
- void LimitFractionValue(Fract *fraction)
- {
- if (*fraction < kFract0) *fraction = kFract0;
- if (*fraction > kFract1) *fraction = kFract1;
- }
-
- void LimitWidthValue(short *windWidth)
- {
- if (*windWidth < 140) *windWidth = 140;
- if (*windWidth > 1200) *windWidth = 1200;
- }
-
- void LimitTextSizeValue(short *textSize)
- {
- if (*textSize < 1) *textSize = 12;
- if (*textSize > 127) *textSize = 12;
- }
-
- #define kWindowName 0
- #define kLoc kWindowName+1
- #define kWidth kLoc+1
- #define kText kWidth+1
- #define kFraction kText+1
- #define kTextFont kFraction+1
- #define kTextSize kTextFont+1
-
- void DoSetup(XCmdPtr paramPtr)
- {
- Point locParam;
- short widthParam;
- Fract fractionParam;
- short textFontParam;
- short textSizeParam;
-
- Rect windowBounds;
- WindowPtr myWindowPtr;
-
- ProgressWindoidInfoHandle progWindInfo;
-
- short progBarTop;
- short progBarWidth;
- short windowHeight;
-
- Str255 windowNameParam;
- Str255 tempStr;
- Str255 paramStr;
- Str255 textParam;
-
- /* PARSE PARAMETERS - Differs from Pascal version in that this
- is not broken out as a separate routine. This is done to avoid
- having to declare all of the above locals as globals. */
-
- if (paramPtr->paramCount < kMinParams) ExitWithError("\pToo few parameters");
- if (paramPtr->paramCount > kMaxParams) ExitWithError("\pToo many parameters");
-
- /* Required Window Name Parameter */
-
- ZeroToPas(paramPtr, *(paramPtr->params[kWindowName]), windowNameParam);
- if (windowNameParam[0] == 0) ExitWithError("\pEmpty window name was given");
-
- /* Required Location Parameter */
-
- ZeroToPas(paramPtr, *(paramPtr->params[kLoc]), paramStr);
- StrToPoint(paramPtr, paramStr, &locParam);
-
- /* locParam is passed in as card-relative, but we will need absolute coordinates.
- As it happens, LocalToGlobal accomplishes this, but the more correct
- way would probably be to use EvalExpr(paramPtr, 'the loc of card window')
- and add that loc to the loc that was passed in. */
-
- LocalToGlobal(&locParam);
-
- /* Optional Width Parameter */
-
- if (paramPtr->paramCount >= kWidth)
- {
- ZeroToPas(paramPtr, *(paramPtr->params[kWidth]), paramStr);
- widthParam = StrToNum(paramPtr, paramStr);
- LimitWidthValue(&widthParam);
- }
- else
- {
- widthParam = 250;
- }
-
- /* Optional Text Parameter */
-
- if (paramPtr->paramCount >= kText)
- {
- ZeroToPas(paramPtr, *(paramPtr->params[kText]), textParam);
- }
- else
- {
- BlockMove("\pProgress:", textParam, 10);
- }
-
- /* Optional Fraction Parameter */
-
- if (paramPtr->paramCount >= kFraction)
- {
- ZeroToPas(paramPtr, *(paramPtr->params[kFraction]), paramStr);
- if (paramStr[0] == 0)
- fractionParam = kFract0;
- else
- {
- fractionParam = X2Frac(StrToExt(paramPtr, paramStr));
- }
- LimitFractionValue(&fractionParam);
- }
- else
- {
- fractionParam = kFract0;
- }
-
- /* Optional TextFont Parameter */
-
- if (paramPtr->paramCount >= kTextFont)
- {
- ZeroToPas(paramPtr, *(paramPtr->params[kTextFont]), paramStr);
- GetFNum(paramStr, &textFontParam);
- }
- else
- {
- textFontParam = 0;
- }
-
- /* Optional TextSize Parameter */
-
- if (paramPtr->paramCount >= kTextSize)
- {
- ZeroToPas(paramPtr, *(paramPtr->params[kTextSize]), paramStr);
- textSizeParam = StrToNum(paramPtr, paramStr);
- LimitTextSizeValue(&textSizeParam);
- }
- else
- {
- textSizeParam = 12;
- }
-
-
- /* End of PARSE PARAMETERS section */
-
- progBarTop = kTextTopSpace + textSizeParam + kTextBottomSpace;
- progBarWidth = widthParam - (2 * kProgBarSideSpace);
-
- windowHeight = progBarTop + kProgBarHeight + kProgBarBottomSpace;
-
- windowBounds.left = locParam.h;
- windowBounds.top = locParam.v;
- windowBounds.right = locParam.h + widthParam;
- windowBounds.bottom = locParam.v + windowHeight;
-
- progWindInfo = (ProgressWindoidInfoHandle) NewHandle(sizeof(ProgressWindoidInfoRecord));
- if (progWindInfo == nil) ExitWithError("\pCouldn’t allocate storage for window variables");
-
- myWindowPtr = NewXWindow(paramPtr, &windowBounds, windowNameParam, false,
- palNoGrowProc, false, true);
-
- if (myWindowPtr == nil)
- {
- DisposHandle((Handle) progWindInfo);
- ExitWithError("\pCouldn’t create XWindow");
- }
-
- myWindowPtr->txFont = textFontParam;
- myWindowPtr->txSize = textSizeParam;
-
- /* All of the XWindow’s variables must be stored in a handle to a
- record (of type ProgressWindoidInfoRecord whose fields are declared at
- the top) and then this handle is stored in the WRefCon of the window once
- it is created. This way they can be accessed again when the window receives
- messages. The handle is destroyed when the window gets its goodbye kiss. */
-
- BlockMove(textParam, (*progWindInfo)->windowText, *textParam+1);
- (*progWindInfo)->windowFraction = fractionParam;
- (*progWindInfo)->progBarTop = progBarTop;
- (*progWindInfo)->progBarWidth = progBarWidth;
-
- SetWRefCon(myWindowPtr, (long) progWindInfo);
-
- } /* DoSetup */
-
- void KillXWindow(XCmdPtr paramPtr, ProgressWindoidInfoHandle progWindInfo, WindowPtr theWindow)
- {
- /* None of the fields in the XWindowInfoRec need to be destroyed,
- just the handle itself. */
- DisposHandle((Handle) progWindInfo);
- }
-
- void DrawProgText(XCmdPtr paramPtr, ProgressWindoidInfoHandle progWindInfo, WindowPtr theWindow)
- {
- Rect textRect;
- FontInfo fInfo;
- short windowWidth;
-
- GetFontInfo(&fInfo);
-
- windowWidth = theWindow->portRect.right - theWindow->portRect.left;
-
- SetRect(&textRect, kTextLeftSideSpace, kTextTopSpace,
- windowWidth, kTextTopSpace + fInfo.ascent + fInfo.descent);
- EraseRect(&textRect);
-
- MoveTo(kTextLeftSideSpace, kTextTopSpace + fInfo.ascent);
- DrawString((*progWindInfo)->windowText);
- }
-
- void DrawProgBar(XCmdPtr paramPtr, ProgressWindoidInfoHandle progWindInfo, WindowPtr theWindow)
- {
- Rect progressBar;
- Rect completionBar;
- Rect unCompleteBar;
- long completionWidth;
- Str255 tempStr;
-
- SetRect(&progressBar, kProgBarSideSpace, (*progWindInfo)->progBarTop,
- kProgBarSideSpace + (*progWindInfo)->progBarWidth,
- (*progWindInfo)->progBarTop + kProgBarHeight);
-
- completionWidth = FracMul(((*progWindInfo)->progBarWidth - 1), (*progWindInfo)->windowFraction);
- SetRect(&completionBar,
- progressBar.left + 1,
- progressBar.top + 1,
- progressBar.left + 1 + completionWidth,
- progressBar.bottom - 1);
-
- SetRect(&unCompleteBar, completionBar.right, completionBar.top,
- kProgBarSideSpace + (*progWindInfo)->progBarWidth - 1,
- completionBar.bottom);
-
- PaintRect(&completionBar);
- EraseRect(&unCompleteBar);
- FrameRect(&progressBar);
- }
-
- void DoUpdate(XCmdPtr paramPtr, ProgressWindoidInfoHandle progWindInfo, WindowPtr theWindow)
- {
- BeginUpdate(theWindow);
-
- EraseRect(&theWindow->portRect);
- DrawProgText(paramPtr, progWindInfo, theWindow);
- DrawProgBar(paramPtr, progWindInfo, theWindow);
-
- EndUpdate(theWindow);
- }
-
- void DoMouseDown(XCmdPtr paramPtr, ProgressWindoidInfoHandle progWindInfo,
- WindowPtr theWindow, EventRecord *theEvent)
- {
-
- switch (FindWindow(theEvent->where,&theWindow)) {
- case inGoAway:
- if (TrackGoAway(theWindow, theEvent->where))
- CloseXWindow(paramPtr, theWindow);
- break;
-
- case inDrag:
- paramPtr->passFlag = true;
- break;
-
- /* case inContent: NOTHING */
- }
- }
-
- Handle GetProperty(XCmdPtr paramPtr, ProgressWindoidInfoHandle progWindInfo,
- WindowPtr theWindow, StringPtr propName)
- {
- Str255 tempStr;
-
- if (StringEqual(paramPtr, propName, "\pProperties"))
- {
- return PasToZero(paramPtr, "\ptext,fraction,width,textFont,textSize");
- }
-
- if (StringEqual(paramPtr, propName, "\pWidth"))
- {
- NumToStr(paramPtr, theWindow->portRect.right - theWindow->portRect.left, tempStr);
- return PasToZero(paramPtr, tempStr);
- }
-
- if (StringEqual(paramPtr, propName, "\pText"))
- {
- return PasToZero(paramPtr, (*progWindInfo)->windowText);
- }
-
- if (StringEqual(paramPtr, propName, "\pFraction"))
- {
- ExtToStr(paramPtr, Frac2X((*progWindInfo)->windowFraction), tempStr);
- return PasToZero(paramPtr, tempStr);
- }
-
- if (StringEqual(paramPtr, propName, "\pTextFont"))
- {
- GetFontName(theWindow->txFont, tempStr);
- return PasToZero(paramPtr, tempStr);
- }
-
- if (StringEqual(paramPtr, propName, "\pTextSize"))
- {
- NumToStr(paramPtr, theWindow->txSize, tempStr);
- return PasToZero(paramPtr, tempStr);
- }
-
- /* This handles the properties: loc, visible (HyperCard supplies them) */
- paramPtr->passFlag = true;
- return nil;
- } /* GetProperty */
-
- void SetProperty(XCmdPtr paramPtr, ProgressWindoidInfoHandle progWindInfo,
- WindowPtr theWindow, StringPtr propName, Handle propVal)
- {
- Str255 tempStr;
-
-
- if (StringEqual(paramPtr, propName, "\pFraction"))
- {
- ZeroToPas(paramPtr,*propVal,tempStr);
-
- (*progWindInfo)->windowFraction = X2Frac(StrToExt(paramPtr, tempStr));
-
- LimitFractionValue(&((*progWindInfo)->windowFraction));
- DrawProgBar(paramPtr, progWindInfo, theWindow);
- return;
- }
-
- if (StringEqual(paramPtr, propName, "\pText"))
- {
- ZeroToPas(paramPtr,*propVal,tempStr);
- BlockMove(tempStr, (*progWindInfo)->windowText, *tempStr+1);
- DrawProgText(paramPtr, progWindInfo, theWindow);
- /* Sometimes the font misbehaves & draws in the progbar area */
- DrawProgBar(paramPtr, progWindInfo, theWindow);
- return;
- }
-
- if (StringEqual(paramPtr, propName, "\pWidth"))
- {
- short newWidth;
- short windowHeight;
- short progBarWidth;
-
- ZeroToPas(paramPtr,*propVal,tempStr);
- newWidth = StrToNum(paramPtr, tempStr);
- LimitWidthValue(&newWidth);
- (*progWindInfo)->progBarWidth = newWidth - (2 * kProgBarSideSpace);
-
- windowHeight = theWindow->portRect.bottom - theWindow->portRect.top;
- SizeWindow(theWindow, newWidth, windowHeight, true);
- InvalRect(&theWindow->portRect);
-
- DrawProgText(paramPtr, progWindInfo, theWindow); /* More or less text may fit now. */
- DrawProgBar(paramPtr, progWindInfo, theWindow); /* The progress bar will be longer or shorter now. */
- return;
- }
-
- if (StringEqual(paramPtr, propName, "\pTextFont"))
- {
- short newFontNumber;
- ZeroToPas(paramPtr,*propVal,tempStr);
- GetFNum(tempStr, &newFontNumber);
- theWindow->txFont = newFontNumber; /* Same as QuickDraw SetFont */
-
- DrawProgText(paramPtr, progWindInfo, theWindow);
- /* Sometimes the font misbehaves & draws in the progbar area */
- DrawProgBar(paramPtr, progWindInfo, theWindow);
- return;
- }
-
- if (StringEqual(paramPtr, propName, "\pTextSize"))
- {
- short newSize;
- short progBarTop;
- short newHeight;
- short windowWidth;
-
- ZeroToPas(paramPtr,*propVal,tempStr);
- newSize = StrToNum(paramPtr, tempStr);
- LimitTextSizeValue(&newSize);
- theWindow->txSize = newSize;
-
- progBarTop = kTextTopSpace + newSize + kTextBottomSpace;
- (*progWindInfo)->progBarTop = progBarTop;
-
- newHeight = progBarTop + kProgBarHeight + kProgBarBottomSpace;
- windowWidth = theWindow->portRect.right - theWindow->portRect.left;
- SizeWindow(theWindow, windowWidth, newHeight, true);
- InvalRect(&theWindow->portRect);
-
- DrawProgText(paramPtr, progWindInfo, theWindow); /* More or less text may fit now. */
- DrawProgBar(paramPtr, progWindInfo, theWindow); /* The progress bar at a different height now. */
- return;
- }
-
- /* This handles the properties: loc, visible (HyperCard will set them) */
- paramPtr->passFlag = true;
- } /* SetProperty */
-
-
- void ProcessEvent(XCmdPtr paramPtr, XWEventInfoPtr myXWEventInfoPtr,
- WindowPtr myWindow, EventRecord *myEvent)
- {
- ProgressWindoidInfoHandle progWindInfo = (ProgressWindoidInfoHandle) GetWRefCon(myWindow);
-
- switch (myEvent->what) {
- case mouseDown:
- DoMouseDown(paramPtr, progWindInfo, myWindow, myEvent);
- break;
- case updateEvt:
- DoUpdate(paramPtr, progWindInfo, myWindow);
- break;
- case app4Evt:
- ShowHide(myWindow, (myEvent->message % 2 != 0));
- break;
- case xCursorWithin:
- paramPtr->passFlag = true;
- break;
- case xGetPropEvt:
- myXWEventInfoPtr->eventResult =
- GetProperty(paramPtr, progWindInfo, myWindow, (StringPtr) myXWEventInfoPtr->eventParams[0]);
- break;
- case xSetPropEvt:
- SetProperty(paramPtr, progWindInfo, myWindow, (StringPtr) myXWEventInfoPtr->eventParams[0], (Handle) myXWEventInfoPtr->eventParams[1]);
- break;
- case xCloseEvt:
- KillXWindow(paramPtr, progWindInfo, myWindow);
- paramPtr->passFlag = true;
- break;
- }
-
- }
-
- void DoEvent(XCmdPtr paramPtr)
- {
- GrafPtr savePort;
- EventRecord myEvent;
- WindowPtr myWindow;
- XWEventInfoPtr myXWEventInfoPtr;
-
- myXWEventInfoPtr = (XWEventInfoPtr) (paramPtr->params[0]);
- myWindow = myXWEventInfoPtr->eventWindow;
- myEvent = myXWEventInfoPtr->event;
-
- GetPort(&savePort);
- SetPort(myWindow);
- ProcessEvent(paramPtr, myXWEventInfoPtr, myWindow, &myEvent);
- SetPort(savePort);
- }
-